home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Ophcrack is a Lanmanager/NTLM hash cracker based on the faster time-memory
- trade-off using rainbow tables.
-
- Created with the help of: Maxime Mueller, Luca Wullschleger, Claude
- Hochreutiner, Andreas Huber and Etienne Dysli.
-
- Copyright 2006 Philippe Oechslin, Cedric Tissieres
-
- Ophcrack is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- Ophcrack is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Ophcrack; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- This program is released under the GPL with the additional exemption
- that compiling, linking, and/or using OpenSSL is allowed.
- */
-
- /* LanManager/NTLM password cracker using a Time-Memory Trade-Off */
-
- /*
- * $Log: ophcrack.c,v $
- * Revision 2.3.3 2006/10/11 tissieres
- * save tables directory, error msg when no tables
- *
- * Revision 2.3.2 2006/10/10 tissieres
- * Patched for FreeBSD
- *
- * Revision 2.3 2006/07/21 tissieres oechslin
- * Support for Mac OS X Intel, NTLM tables, linear search, Windows preload, ...
- *
- * Revision 2.2 2006/03/20 tissieres oechslin dysli
- * Support for extended charset, memory management
- *
- * Revision 2.1 2005/12/06 tissieres
- * Added tables modification feature, readahead
- *
- * Revision 2.0 2005/03/24 tissieres
- * Modified for GUI
- *
- * Revision 1.1 2004/09/13 14:26:02 oechslin
- * Fixed bug in -q option
- *
- * Revision 1.0 2004/07/10 19:06:46 oechslin
- * Initial revision
- *
- *
- */
-
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <ctype.h>
- #ifndef WIN32
- #include <sys/times.h>
- #include <sys/mman.h>
- /* On *BSD, MAP_ANON is used instead of MAP_ANONYMOUS */
- #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
- #define MAP_ANONYMOUS MAP_ANON
- #endif
- #if HAVE_SYS_SYSINFO_H
- #include <sys/sysinfo.h>
- #elif HAVE_SYS_SYSCTL_H
- #include <sys/sysctl.h>
- #endif
- #if HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #else /* WIN32 */
- #include <sys/time.h>
- #include <windows.h>
- #endif /* WIN32 */
- #include <sys/stat.h>
-
-
- #include "make_hash.h"
- #include "make_redux.h"
- #include "ophcrack.h"
-
- #ifdef WIN32
- #define bzero(p, l) memset(p, 0, l)
- #endif /* WIN32 */
-
- #define RAM_FOR_SYSTEM 150 //amount of ram left for the system
- #define NB_CHECKPOINTS 2
-
- /* command line options */
- int magic_chains = 0,
- stats = 0,
- verbose = 0,
- batch_mode = 0,
- batch_tables = 1,
- quiet = 0,
- ident_col = 99999,
- cols = 0,
- offset = 0,
- first_table = 0,
- last_table = 20,
- chkpt1 = -1,
- chkpt2 = -1;
-
- int checkpoint_value[2];
-
- int STOP = 0,
- open_tables = 0,
- last_table_save,
- batch_tables_save,
- table_type = -1,
- chars_size = -1;
-
- unsigned char
- lm_hash1[MAX_HASH+1][8]={{0}},
- lm_hash2[MAX_HASH+1][8]={{0}},
- nt_hash[MAX_HASH+1][16]={{0}},
- empty_hash[8]={0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee},
- empty_nt_hash[16]={0x31,0xd6,0xcf,0xe0,0xd1,0x6a,0xe9,0x31,0xb7,0x3c,0x59,0xd7,0xe0,0xc0,0x89,0xc0};
-
- int to_go, hashes=0, n=0, done1[MAX_HASH+1]={0},done2[MAX_HASH+1]={0}, userid[MAX_HASH+1], done_nt[MAX_HASH+1]={0};
-
- char directory[128], info[MAX_HASH+1][64]={{0}}, password[MAX_HASH+1][16]={{0}},
- password1[MAX_HASH+1][8]={{0}}, password2[MAX_HASH+1][8]={{0}};
-
- char crack_type[] = "LM";
- int crack_type_num = 0;
-
- #ifndef WIN32
- FILE *startfile[20],*endfile[20],*indexfile[20];
- #else
- HANDLE startfile[20], endfile[20], indexfile[20];
- unsigned char *startbuff[20],*endbuff[20],*indexbuff[20] = {0};
- #endif
- int F_INDEX=0, F_START=0, F_END=0;
-
- unsigned long long int offset_nt[] = {0ULL, 95ULL, 9120ULL, 866495ULL,
- 82317120ULL, 7820126495ULL, 742912017120ULL,
- 4264526623328ULL};
- extern unsigned char nt_chars_low36[];
- extern unsigned char nt_chars_alphanum62[];
- extern unsigned char nt_chars_ext95[];
-
- /* statistics */
- int n_search = 0,
- n_fseek = 0,
- n_hashredux = 0,
- n_false = 0,
- n_false_redux = 0,
- n_match = 0,
- n_loop = 0,
- n_found = 0,
- n_cp_false = 0;
-
- struct tms n_times;
- int ticks;
- clock_t n_start_time, laps_time;
-
- unsigned long int size_to_clean = 0;
-
- #ifdef WIN32
- char *
- strsep(char** stringp, const char* delim)
- {
- char *s;
- const char *spanp;
- int c, sc;
- char *tok;
-
- if ((s = *stringp) == NULL)
- return (NULL);
- for (tok = s;;) {
- c = *s++;
- spanp = delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = 0;
- *stringp = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
- }
-
- #endif
-
-
- /* void usage(char *name)
- {
- printf("usage %s [-pvsb -d directory -f first -i row -l last -n tables] -t columns lmhash[:nthash]ªhash_file_name\n",name);
- printf(" -d directory where tables saved\n");
- printf(" -t columns per table\n");
- printf(" -o table offset (if not equal to t)\n");
- printf(" -i appliy identical redux starting at this column \n");
- printf(" -v verbose mode\n");
- printf(" -s generate statistics\n");
- printf(" -q quiet (no progress indication)\n");
- printf(" -f first table (default 0)\n");
- printf(" -l last table (default 2^31-1)\n");
- printf(" -n number of tables to use at a time\n");
- printf("\n\n");
- printf(" Hashes can be provided in the following hex formats:\n");
- printf(" lmhash\n");
- printf(" lmhash:nthash\n");
- printf(" username:userid:lmhash:nthash:other fieds (as provided by pwdump)\n");
- printf(" or the name of a file containing such hashes, one on each line.\n\n");
-
- exit(-1);
- }
- */
-
- /* void print_stats() {
- clock_t t;
-
- t = times(&n_times);
- printf("\nStatistics: \n hash-redux calculations: %d\n",
- n_hashredux);
- printf(" endpoint searched %d\n fseek operations %d\n",
- n_search, n_fseek);
- printf(" matches found %d\n false alarms %d\n",
- n_match,
- n_false);
- printf(" hash-redux operations per false alarms %d\n",
- (n_false? n_false_redux/n_false: 0));
- printf(" time elapsed %5.2fs\n\n",
- (float)(t-n_start_time)/ ticks );
- }
- */
-
- void init_stats() {
- n_hashredux=0;
- n_search=0;
- n_fseek=0;
- n_false=0;
- n_false_redux=0;
- n_match=0;
- #ifndef WIN32
- n_start_time = times(&n_times);
- #else /* WIN32 */
- n_start_time = clock();
- #endif /* WIN32 */
- }
-
-
-
- /* Open all the files
- =================== */
- int open_files()
- {
- unsigned char filename[256];
-
- int table;
- first_table=0;
- #ifdef WIN32
- int error;
- #endif
-
- /* for all available tables */
- for (table=first_table; table<=last_table; table++) {
-
- /* end points */
- sprintf((char *)filename,"%s/table%d.bin",directory,table);
- #ifndef WIN32
- if (!(endfile[table]=fopen((char *)filename,"r"))) {
- #else
- endfile[table]= CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_SEQUENTIAL_SCAN, 0);
- if (GetLastError()) {
- #endif
- last_table = table-1;
- break; /* all tables searched */
- }
-
- /* starting points */
- sprintf((char *)filename,"%s/table%d.start",directory,table);
- #ifndef WIN32
- if (!(startfile[table]=fopen((char *)filename,"r")))
- #else
- startfile[table]= CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_SEQUENTIAL_SCAN, 0);
- if (GetLastError())
- #endif
- g_print ("cannot open table file");
-
- /* index table */
- sprintf((char *)filename,"%s/table%d.index",directory,table);
- #ifndef WIN32
- if (!(indexfile[table]=fopen((char *)filename,"r")))
- #else
- indexfile[table]= CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_SEQUENTIAL_SCAN, 0);
- if (GetLastError())
- #endif
- g_print ("cannot open index file");
- }
-
- if (table != first_table) {
- //if (verbose) printf(" found tables %d through %d\n",first_table, last_table);
- open_tables = 1;
- last_table_save = last_table;
- batch_tables_save = batch_tables;
-
- return 1;
- } else {
- printf(" found no tables!\n");
- return 0;
- }
- }
-
- int close_files()
- {
- int table;
- #ifdef WIN32
- int error;
- #endif
-
- batch_tables = batch_tables_save;
- last_table = last_table_save;
- first_table = 0;
- open_tables = 0;
-
- /* for all available tables */
- for (table=first_table; table<=last_table; table++) {
-
- #ifndef WIN32
- fclose(endfile[table]);
- fclose(startfile[table]);
- fclose(indexfile[table]);
- #else
- CloseHandle(endfile[table]);
- CloseHandle(startfile[table]);
- CloseHandle(indexfile[table]);
- if (F_START && startbuff[table]) {
- free(startbuff[table]);
- startbuff[table] = 0;
- }
- if (F_END && endbuff[table]){
- free(endbuff[table]);
- endbuff[table] = 0;
- }
- if (F_INDEX && indexbuff[table]){
- free(indexbuff[table]);
- indexbuff[table] = 0;
- }
- #endif
- }
- F_INDEX=0; F_START=0; F_END=0;
- return 1;
- }
-
- int unbin95(unsigned int input, unsigned char *output) {
-
- int i = 0;
- for (i=4; i>=0; i--) {
- output[i]=nt_chars_ext95[input%95];
- input/=95;
- }
- return 1;
- }
-
- unsigned long long int bin43(unsigned char *input) {
- unsigned long long int sum = 0;
- int i,l;
-
- l = (int) strlen((char *)input);
-
- if (l<7)
- for (i=0; i<l && i<6; i++)
- sum = sum*95 + (unsigned long long int)(strchr((char *)nt_chars_ext95,input[i]) - (char*)nt_chars_ext95);
-
- else if (l==7)
- for (i=0; i<7; i++)
- sum = sum*62 + (unsigned long long int)(strchr((char *)nt_chars_alphanum62,input[i]) - (char*)nt_chars_alphanum62);
-
- else if (l==8)
- for (i=0; i<8; i++)
- sum = sum*36 + (unsigned long long int)(strchr((char *)nt_chars_low36,input[i]) - (char*)nt_chars_low36);
-
- sum += offset_nt[l-1];
-
-
- return sum;
- }
-
-
- /* Find a end of chain in a table and return the corresponding
- start of chain using three files: index, end and start
- ================================================================
- */
-
- int binsearch(int table, char *pw, char *startpw)
- {
-
- if (!crack_type_num) { //LM CRACK
- int i,l,l2;
- unsigned int prefix,start,offset;
- unsigned short int postfix;
- unsigned short int p1[200];
- int high,low;
- char *p;
- #ifdef WIN32
- DWORD dwRead;
- int* p_index = NULL;
- int* p_start = NULL;
- unsigned short int* p_end = NULL;
- #else
- int dwRead;
- #endif
-
-
- l2 = strlen(pw);
-
- /*calculate prefix from first 4 bytes */
- prefix=0;
- l=(l2<4 ? l2 : 4);
- offset=chars_size*chars_size*chars_size*chars_size;
- for (i=0; i<4; i++) {
- p=strchr((char *)charset,pw[i]);
- if (i< l) prefix=prefix*chars_size+p-(char*)charset;
- else {prefix+=offset;offset/=chars_size;}
- }
- //g_print("\nbinsearch: prefix %u\n",prefix);
- /*calculate postfix from last 3 bytes */
- postfix=0;
- l=(l2>4 ? l2-4 : 0); offset=chars_size*chars_size*chars_size;
- for (i=0; i<3; i++) {
- p=strchr((char *)charset,pw[i+4]);
- if (i< l) postfix=postfix*chars_size+p-(char*)charset;
- else { postfix+=offset;offset/=chars_size; }
- }
- //g_print("binsearch: postfix %hu\n",postfix);
-
- /* look-up range for this prefix in the index */
- #ifndef WIN32
- fseek(indexfile[table],4*prefix,SEEK_SET);
- fread(&low,sizeof(low),1,indexfile[table]);
- #else
- if (!F_INDEX) {
- SetFilePointer(indexfile[table], 4*prefix, NULL, FILE_BEGIN);
- ReadFile(indexfile[table], &low, sizeof(low), &dwRead, NULL);
- } else {
- p_index = (int*)(indexbuff[table]+4*prefix);
- low = *p_index;
- }
- #endif
- n_fseek++;
- //g_print("binsearch: low=%d\n",low);
- if (low) {
- #ifndef WIN32
- fread(&high,sizeof(high),1,indexfile[table]);
- #else
- if (!F_INDEX)
- ReadFile(indexfile[table], &high, sizeof(high), &dwRead, NULL);
- else {
- p_index++;
- high = *p_index;
- }
- #endif
- //g_print("binsearch: high=%d\n",high);
- if (high) {
- //g_print("binsearch: low=%d high=%d\n",low, high);
- #ifndef WIN32
- fseek(endfile[table],(low)*2, SEEK_SET);
- fread(&p1,sizeof(unsigned short int),(high-low),endfile[table]);
- #else
- if (!F_END) {
- SetFilePointer(endfile[table], (low)*2, NULL,FILE_BEGIN);
- ReadFile(endfile[table], &p1, (high-low)*sizeof(unsigned short int), &dwRead, NULL);
- } else {
- //p_end = (unsigned short int*)(endbuff[table]+((low)*2));
- memcpy(p1, (unsigned short int*) (endbuff[table]+((low)*2)), (high-low)*sizeof(unsigned short int));
- }
- #endif
- n_fseek++;
- i=0;
- while (i<(high-low)) {
- if (p1[i]==postfix)
- break; /* found! */
- else
- i++;
- }
- if (i == (high-low)) return 0;
- }
- }
-
- /* read start and change it to ascii: */
- #ifndef WIN32
- fseek(startfile[table],(low+i)*4,SEEK_SET);
- fread(&start,sizeof(start),1,startfile[table]);
- #else
- if (!F_START) {
- SetFilePointer(startfile[table], (low+i)*4, NULL, FILE_BEGIN);
- ReadFile(startfile[table], &start, sizeof(start), &dwRead, NULL);
- } else {
- p_start = (int*)(startbuff[table]+((low+i)*4));
- start = *p_start;
- }
- #endif
- n_fseek++;
- // g_print("start = %d", start);
-
- /* Extract checkpoint from start */
- checkpoint_value[0] = (start>>30) & 0x1;
- checkpoint_value[1] = (start>>31) & 0x1;
-
- start &= 0x3FFFFFFF;
-
- startpw[6]=0;
- startpw[7]=0;
- for(i=5;i>=0;i--) {
- startpw[i] = charset[start%36]; /* WARNING! change 36 into CHARS_SIZE */
- start/=36;
- }
- } else { //NT CRACK
-
- int i,l,l2;
- unsigned int prefix,start;
- unsigned short int postfix;
- unsigned short int p1[200];
- unsigned long long int pw_bin;
- int high,low;
- char *p;
- #ifdef WIN32
- DWORD dwRead;
- int* p_index = NULL;
- int* p_start = NULL;
- unsigned short int* p_end = NULL;
- #else
- int dwRead;
- #endif
-
- pw_bin = bin43((unsigned char *)pw);
-
- prefix = (unsigned int) (pw_bin >>18 & 0x00000000FFFFFFFF);
- postfix = (unsigned short int) (pw_bin & 0x000000000000FFFF);
-
- /* look-up range for this prefix in the index */
- #ifndef WIN32
- fseek(indexfile[table],4*prefix,SEEK_SET);
- fread(&low,sizeof(low),1,indexfile[table]);
- #else
- if (!F_INDEX) {
- SetFilePointer(indexfile[table], 4*prefix, NULL, FILE_BEGIN);
- ReadFile(indexfile[table], &low, sizeof(low), &dwRead, NULL);
- } else {
- p_index = (int*)(indexbuff[table]+4*prefix);
- low = *p_index;
- }
- #endif
- n_fseek++;
- //g_print("binsearch: low=%d\n",low);
- if (low) {
- #ifndef WIN32
- fread(&high,sizeof(high),1,indexfile[table]);
- #else
- if (!F_INDEX)
- ReadFile(indexfile[table], &high, sizeof(high), &dwRead, NULL);
- else {
- p_index++;
- high = *p_index;
- }
- #endif
- //g_print("binsearch: high=%d\n",high);
- if (high) {
- //g_print("binsearch: low=%d high=%d\n",low, high);
- #ifndef WIN32
- fseek(endfile[table],(low)*2, SEEK_SET);
- fread(&p1,sizeof(unsigned short int),(high-low),endfile[table]);
- #else
- if (!F_END) {
- SetFilePointer(endfile[table], (low)*2, NULL,FILE_BEGIN);
- ReadFile(endfile[table], &p1, (high-low)*sizeof(unsigned short int), &dwRead, NULL);
- } else {
- //p_end = (unsigned short int*)(endbuff[table]+((low)*2));
- memcpy(p1, (unsigned short int*) (endbuff[table]+((low)*2)), (high-low)*sizeof(unsigned short int));
- }
- #endif
- n_fseek++;
- i=0;
- while (i<(high-low)) {
- if (p1[i]==postfix)
- break; /* found! */
- else
- i++;
- }
- if (i == (high-low)) return 0;
- }
- }
-
- /* read start and change it to ascii: */
- #ifndef WIN32
- fseek(startfile[table],(low+i)*4,SEEK_SET);
- fread(&start,sizeof(start),1,startfile[table]);
- #else
- if (!F_START) {
- SetFilePointer(startfile[table], (low+i)*4, NULL, FILE_BEGIN);
- ReadFile(startfile[table], &start, sizeof(start), &dwRead, NULL);
- } else {
- p_start = (int*)(startbuff[table]+((low+i)*4));
- start = *p_start;
- }
- #endif
- n_fseek++;
- // g_print("start = %d", start);
-
- startpw[5]=0;
- startpw[6]=0;
- startpw[7]=0;
- unbin95(start, (unsigned char *)startpw);
-
-
- }
- return 1;
- }
-
-
- /* Find the password corresponing to HASH in a given table, at a given
- column and starting with a given reduction function
- =================================================== */
-
- int find(unsigned char *hash, char *found, int col, int table)
- {
- if (!crack_type_num) { // LM CRACK
- unsigned char h[8];
- static char pw[8], start[8];
- static int i,l;
- int checkpoint_found[2]={0};
-
- //g_print("\nfind: col=%d table=%d\n",col,table);
-
- set_redux(col, table);
-
- /* advance to end of chain */
-
- /* we can save this work if we are in parallel mode, above ident_redux and
- * not in the first table and doing the tree-table optimization... */
-
- if (table==first_table || col < ident_col) {
- make_redux(hash,(unsigned char *)pw);
- //g_print("find: %d,%s ",n_redux,pw);
- for (l=1; l<cols-col; l++) {
- make_hash((unsigned char *)pw,h);
- next_redux();
- make_redux(h,(unsigned char *)pw);
- //g_print("%d,%s ",n_redux,pw);
- if ((chkpt1 != -1) && (chkpt2 !=-1)) {
- if ((col+l+1) == chkpt1)
- checkpoint_found[0] = pw[0] & 0x1;
- if ((col+l+1) == chkpt2)
- checkpoint_found[1] = pw[0] & 0x1;
- }
- }
- n_hashredux+=l;
- //g_print("%-7.7s\n",pw);
- //g_print("find: n_hashredux=%d l=%d\n",n_hashredux,l);
- }
-
- while (gtk_events_pending ())
- gtk_main_iteration ();
-
- /* look up the end in the table and get the start */
- if (binsearch(table,pw,start)) {
- n_match++;
- if ((chkpt1 != -1) && (chkpt2 !=-1)) {
- if (!((checkpoint_value[0] == checkpoint_found[0])
- && (checkpoint_value[1] == checkpoint_found[1]))) {
- n_cp_false++;
- return 0;
- }
- }
-
- set_redux(0, table);
- /* advance to the colunm that we are exploring */
- for (i=l; i<=cols-1; i++) {
- make_hash((unsigned char *)start,h);
- make_redux(h,(unsigned char *)start);
- next_redux();
- n_hashredux++;
- }
- make_hash((unsigned char *)start,h);
- /* check if we get the same hash: */
- if (!memcmp(&h,hash,sizeof(h))) {
- strncpy(found,start,8);
- //g_print("find: found in table %d\n",table);
- return 1;
- }
- else {
- /* false alarm! */
- n_false++;
- n_false_redux += cols-l;
- }
- }
- } else { //NT CRACK
-
- unsigned char h[16];
- static char pw[16], start[16];
- static int i,l;
-
- set_redux(col, table);
-
- /* advance to end of chain */
-
- if (table==first_table || col < ident_col) {
- make_redux(hash,(unsigned char *)pw);
- //g_print("find: %d,%s ",n_redux,pw);
- for (l=1; l<cols-col; l++) {
- make_nthash(pw,(char *)h);
- next_redux();
- make_redux(h,(unsigned char *)pw);
- //g_print("%d,%s ",n_redux,pw);
- }
- n_hashredux+=l;
- //g_print("%-7.7s\n",pw);
- //g_print("find: n_hashredux=%d l=%d\n",n_hashredux,l);
- }
-
- while (gtk_events_pending ())
- gtk_main_iteration ();
-
- /* look up the end in the table and get the start */
- if (binsearch(table,pw,start)) {
- n_match++;
-
- set_redux(0, table);
- /* advance to the colunm that we are exploring */
- for (i=l; i<=cols-1; i++) {
- make_nthash(start,(char *)h);
- make_redux(h,(unsigned char *)start);
- next_redux();
- n_hashredux++;
- }
- make_nthash(start,(char *)h);
- /* check if we get the same hash: */
- if (!memcmp(&h,hash,sizeof(h))) {
- strncpy(found,start,16);
- //g_print("find: found in table %d\n",table);
- return 1;
- }
- else {
- /* false alarm! */
- n_false++;
- n_false_redux += cols-l;
- }
- }
-
- }
- return 0;
- }
-
-
- /* Read two halfs of LMHash and possibly NTHash and info from string */
- int get_hashes(unsigned char lmhash_1[], unsigned char lmhash_2[],
- char nthash[], unsigned char *info, int *userid,
- char *password1, char *password2, char *password,
- int *done1, int *done2, char *h)
- {
- /* following formats are supported:
- lmhash
- lmhash:nthash
- username:userid:lmhash:nthash:passwd1:passwd2:passwd (like pwdump2)
- */
-
- unsigned int i,k,l;
- char *p[8] = {0};
- unsigned char *tmp;
- l=0;
- p[l]=strsep(&h,":");
- while (l<8){
- l++;
- if (!(p[l]=strsep(&h,":")) ) break;
- }
- if (l==7) {
- if (strcmp(p[0],"")) strncpy((char *)info,p[0],64);
- if (strcmp(p[1],"")) *userid = atoi(p[1]);
- if (!strcmp(p[2],"NO PASSWORD*********************")) {
- memcpy(lmhash_1, empty_hash, 8);
- memcpy(lmhash_2, empty_hash, 8);
- }
- else
- for (i=0; i<8; i++) {
- if (sscanf(p[2]+2*i,"%2x",&k) !=1 )
- return 0;
- lmhash_1[i]=(unsigned char)k;
-
- if (sscanf(p[2]+2*i+16,"%2x",&k) !=1 )
- return 0;
- lmhash_2[i]=(unsigned char)k;
- }
-
- if (strcmp(p[3],"")){
- if (!strcmp(p[3],"NO PASSWORD*********************"))
- memcpy(nthash, empty_nt_hash, 16);
- else
- for (i=0;i<16;i++)
- if (sscanf(p[3]+2*i,"%2hhx",(unsigned char *)&nthash[i])!=1)
- return 0;
- } else
- nthash[0]=0;
- /* thanks to BaLP */
- if (strcmp(p[4],"")) {
- strncpy(password1, p[4], strlen(p[4]));
- for (tmp = (unsigned char *)password1; (*tmp = (*tmp == 193U ? ':' : *tmp)); ++tmp);
- *done1=1;
- }
- if (strcmp(p[5], "")) {
- strncpy(password2, p[5], strlen(p[5]));
- for (tmp = (unsigned char *)password2; (*tmp = (*tmp == 193U ? ':' : *tmp)); ++tmp);
- *done2=1;
- }
- strncpy(password, p[6], strlen(p[6]));
- for (tmp = (unsigned char *)password; (*tmp = (*tmp == 193U ? ':' : *tmp)); ++tmp);
-
-
- } else {
-
- if (!strcmp(p[0],"NO PASSWORD*********************")) {
- memcpy(lmhash_1, empty_hash, 8);
- memcpy(lmhash_2, empty_hash, 8);
- }
- else
- for (i=0; i<8; i++) {
- if (sscanf(p[0]+2*i,"%2x",&k) !=1 )
- return 0;
- lmhash_1[i]=(unsigned char)k;
-
- if (sscanf(p[0]+2*i+16,"%2x",&k) !=1 )
- return 0;
- lmhash_2[i]=(unsigned char)k;
- }
-
- if (l>1) {
-
- if (strcmp(p[1],"")){
- if (!strcmp(p[1],"NO PASSWORD*********************"))
- memcpy(nthash, empty_nt_hash, 16);
- else
- for (i=0;i<16;i++)
- if (sscanf(p[1]+2*i,"%2hhx",(unsigned char *)&nthash[i])!=1)
- return 0;
- }
- }
- }
-
- return 1;
- }
-
- int read_line(char *line) {
- if (get_hashes(lm_hash1[hashes],lm_hash2[hashes],
- (char *)nt_hash[hashes],(unsigned char *)info[hashes], &userid[hashes],
- password1[hashes], password2[hashes],
- password[hashes],&done1[hashes], &done2[hashes],line)) {
- hashes++;
- return 1;
- } else {
- return 0;
- }
- }
-
- int remove_line(int hash) {
- int diff;
-
- diff=hashes-hash;
- if (diff>0) {
- memmove(lm_hash1[hash], lm_hash1[hash+1], diff*sizeof(lm_hash1[hash]));
- memmove(lm_hash2[hash], lm_hash2[hash+1], diff*sizeof(lm_hash2[hash]));
- memmove(nt_hash[hash], nt_hash[hash+1], diff*sizeof(nt_hash[hash]));
- memmove(info[hash], info[hash+1], diff*sizeof(info[hash]));
- memmove(&userid[hash], &userid[hash+1], diff*sizeof(&userid[hash]));
- memmove(password1[hash], password1[hash+1], diff*sizeof(password1[hash]));
- memmove(password2[hash], password2[hash+1], diff*sizeof(password2[hash]));
- memmove(password[hash], password[hash+1], diff*sizeof(password[hash]));
- memmove(&done1[hash], &done1[hash+1], diff*sizeof(&done1[hash]));
- memmove(&done2[hash], &done2[hash+1], diff*sizeof(&done2[hash]));
- }
- hashes--;
- }
-
- int resolve_nt_hash(char p1[], char p2[], char h[], char pw[])
- {
- unsigned int i;
- unsigned int k=0,l;
- unsigned char md4[17],*p;
-
- bzero(pw,15);
- strcpy(pw,p1);
- strcpy(&pw[7],p2);
-
- md4[16]=0;
-
- for (i=0; i<16384; i++) {
- l = k ^ i ^ (i>>1);
- k = i ^ (i>>1);
- p = (unsigned char *)pw; while ((l=l>>1)) p++;
- *p=(*p>91?toupper(*p):tolower(*p));
- make_nthash(pw,(char *)md4);
-
- if (!memcmp(md4,h,16)) {
- return 1;
- }
- }
- return 0;
- }
-
-
- /* Display password and progress indication */
- void display(int h, int k)
- {
- int i;
-
- if (h==-1)
- printf("%-32s : %-14s\n","username or lmhash","password");
- if (h>= 0) {
- if (info[h][0])
- printf("%-32s : ",info[h]);
- else {
- for (i=0; i<8; i++) printf("%02hhx",lm_hash1[h][i]);
- for (i=0; i<8; i++) printf("%02hhx",lm_hash2[h][i]);
- printf(" : ");
- }
- if (resolve_nt_hash(password1[h],password2[h], (char *)nt_hash[h],password[h]) )
- printf("%-14s \n",password[h]);
- else
- printf("%-7s%-7s \n",password1[h],password2[h]);
- }
-
- if (!quiet) {
- #ifndef WIN32
- laps_time = times(&n_times);
- #else /* WIN32 */
- laps_time = clock();
- #endif /* WIN32 */
- printf("[tables:%d-%d,%2d%% passwords:%d/%d seconds/pw:%.2f]\r",
- first_table,
- last_table,
- 100-(100*k)/cols,
- n_found, hashes,
- (n_found?(float)(laps_time - n_start_time)/ticks/n_found:0));
- }
- }
-
- int read_file(char* filename) {
- char c;
- char *line;
- int size = 199;
- FILE *hash_file;
-
- clear_passwd_arrays();
-
- hashes = 0;
- n_found = 0;
-
- /* get hash from command line or from file: */
-
- if (!(hash_file=fopen(filename,"r"))) {
- //g_print("%s is neither a valid hash or a filename\n\n\n",filename);
- return 0;
- }
- line = malloc(size+1);
-
- /* Get hashes from file into table */
- fgets(line, 199, hash_file);
- if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; //remove newline
- while (!feof(hash_file) && (hashes <MAX_HASH)) {
- if (get_hashes(lm_hash1[hashes],lm_hash2[hashes],
- (char *)nt_hash[hashes],(unsigned char *)info[hashes], &userid[hashes],
- password1[hashes], password2[hashes],
- password[hashes],&done1[hashes], &done2[hashes],line))
- //printf("invalid hash found in hash file: %s\n",line);
- //else
- hashes++;
- fgets(line, 199, hash_file);
- if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
- }
- if (hashes == MAX_HASH)
- show_error_max_hash();
-
- fclose(hash_file);
- return hashes;
- }
-
-
- void clear_passwd_arrays(void) {
- int i;
-
- for (i=0; i<hashes; i++) {
- bzero(info[i], sizeof(info[i]));
- bzero(lm_hash1[i], sizeof(lm_hash1[i]));
- bzero(lm_hash2[i], sizeof(lm_hash2[i]));
- bzero(nt_hash[i], sizeof(nt_hash[i]));
- userid[i]=0;
- bzero(password1[i], sizeof(password1[i]));
- bzero(password2[i], sizeof(password2[i]));
- bzero(password[i], sizeof(password[i]));
- done1[i]=0;
- done2[i]=0;
- }
- }
-
- int auto_detect_tables(char *directory) {
- unsigned char filename[256];
- unsigned char configfilename[256];
- FILE *file;
- unsigned int buff;
- char *parameter;
- FILE *configfile;
- char *line = (char *)malloc(100*sizeof(char));
-
-
- /* test if we know the tables */
- sprintf((char *)filename,"%s/table0.bin",directory);
- if (file=fopen((char *)filename, "r")) {
- fread(&buff, sizeof(int), 1, file);
-
- switch(buff) {
-
- case 0x3cc21790 : table_type = 0; cols=10000; batch_tables=1;
- last_table=3; offset=10000; break;
- case 0x0fa2031c : table_type = 1; cols=5000; offset = 10000;
- batch_tables = 1; last_table = 3; break;
- case 0x0e3402df :
- case 0xc7ed7df5 :
- sprintf((char *)configfilename,"%s/tables.cfg",directory);
- if (!(configfile=fopen((char *)configfilename,"r"))) {
- return 0;
- }
- else {
- while( fgets(line, 99, configfile) != NULL ) {
- parameter = (char *)strsep(&line,"=");
- if (!strcmp(parameter, "table_type"))
- table_type = atoi(line);
- if (!strcmp(parameter, "cols"))
- cols = atoi(line);
- if (!strcmp(parameter, "offset"))
- offset = atoi(line);
- if (!strcmp(parameter, "chkpt1"))
- chkpt1 = atoi(line);
- if (!strcmp(parameter, "chkpt2"))
- chkpt2 = atoi(line);
- if (!strcmp(parameter, "crack_type"))
- strncpy(crack_type, line, 2);
- }
- }
- break;
- default: fclose(file); return 0; break;
- }
- fclose(file);
-
- return 1;
- } else return 0;
-
- }
-
- int find_tables() {
- #ifdef WIN32
- strcpy(directory, "5000");
- #else
- snprintf(directory, 127, "%s/5000", TDIR);
- #endif
- if (access(directory, F_OK) == 0) {
- auto_detect_tables(directory);
- }
- else {
- #ifdef WIN32
- strcpy(directory, "10000");
- #else
- snprintf(directory, 127, "%s/10000", TDIR);
- #endif
-
- if (access(directory, F_OK) == 0) {
- auto_detect_tables(directory);
- }
- }
-
- n_found = 0;
-
- if (!offset) offset=cols;
-
- }
-
- #ifndef WIN32
- int clean_ram(unsigned long int size) {
- /* clean page cache (very dirty...) */
-
- unsigned long int i;
- char *ptr;
-
- show_clean_window();
- ptr = (char*)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (ptr!= MAP_FAILED) {
- for (i=0; i<size; ++i) {
- *(ptr + i) = 1;
- }
- munmap(ptr, size);
- }
- hide_readahead_window();
- return 0;
- }
- #endif
-
- int evaluate_ram() {
-
- #ifdef WIN32
- MEMORYSTATUS stat;
- DWORD filesize[3];
- #else
- struct stat buf;
- //struct sysinfo info;
- size_t filesize[3];
- int fd;
- #endif
- #ifdef HAVE_SYS_SYSINFO_H
- struct sysinfo info;
- #elif defined(HAVE_SYS_SYSCTL_H)
- int mib[2] = {CTL_HW, HW_PHYSMEM}, mem;
- size_t len;
- #endif
- long int totalram,freeram;
-
- /* calculate table size*/
- #ifndef WIN32
- fd = fileno(indexfile[first_table]);
- fstat(fd, &buf);
- filesize[0] = (size_t)buf.st_size;
- fd = fileno(endfile[first_table]);
- fstat(fd, &buf);
- filesize[1] = (size_t)buf.st_size +filesize[0];
- fd = fileno(startfile[first_table]);
- fstat(fd, &buf);
- filesize[2] = (size_t)buf.st_size +filesize[1];
- #else
- filesize[0] = GetFileSize(indexfile[first_table], NULL);
- filesize[1] = GetFileSize(endfile[first_table], NULL) + filesize[0];
- filesize[2] = GetFileSize(startfile[first_table], NULL) +filesize[1];
- #endif
- batch_tables=1;
- size_to_clean = (unsigned long int) filesize[2];
-
- /* retrieve system info */
- #if HAVE_SYS_SYSINFO_H
- sysinfo(&info);
- totalram = (long int)info.totalram - RAM_FOR_SYSTEM*1024*1024;
- freeram = (long int)info.freeram;
- #elif HAVE_SYS_SYSCTL_H
- len = sizeof(mem);
- if (sysctl(mib, 2, &mem, &len, NULL, 0) == 0) {
- totalram = mem - RAM_FOR_SYSTEM*1024*1024;
- } else {
- perror("sysctl");
- exit(-1);
- }
-
- mib[1] = HW_USERMEM;
- len = sizeof(mem);
- if (sysctl(mib, 2, &mem, &len, NULL, 0) == 0) {
- freeram = mem;
- } else {
- perror("sysctl");
- exit(-1);
- }
- #elif defined(WIN32)
- GlobalMemoryStatus (&stat);
- totalram = 0;
- freeram = (long int)stat.dwAvailPhys;
- #else
- #error do not know how to get RAM information
- #endif
-
- #ifndef WIN32
- //g_print("%d%d%d %d %u %d %d\n", F_INDEX, F_END, F_START, batch_tables, batch_tables*filesize[2], freeram, totalram);
- if (totalram < freeram) totalram=freeram;
-
- if (size_to_clean > totalram)
- size_to_clean = totalram;
- while ((size_to_clean*batch_tables) < totalram) {
- batch_tables++;
- }
- if (batch_tables >1) batch_tables--;
- if (batch_tables > last_table +1)
- batch_tables = last_table+1;
-
- size_to_clean *= batch_tables;
- //g_print("%d%d%d %d %u %d %d\n", F_INDEX, F_END, F_START, batch_tables, batch_tables*filesize[2], freeram, totalram);
-
- /* clean ram */
- clean_ram(size_to_clean);
-
- /* reevaluate available ram */
- #if HAVE_SYS_SYSINFO_H
- sysinfo(&info);
- freeram = (long int)info.freeram;
- #elif HAVE_SYS_SYSCTL_H
- mib[0] = CTL_HW;
- mib[1] = HW_USERMEM;
- len = sizeof(mem);
- if (sysctl(mib, 2, &mem, &len, NULL, 0) == 0) {
- freeram = mem;
- } else {
- perror("sysctl");
- exit(-1);
- }
- #else
- #error do not know how to get RAM information
- #endif
- #endif
-
- #if HAVE_READAHEAD
- if (freeram < size_to_clean) {
- if (filesize[0]>freeram) {
- F_INDEX=1; F_END = 0; F_START = 0; batch_tables = 1;
- }
- else if (filesize[1]>freeram) {
- F_INDEX=1; F_END = 1; F_START = 0; batch_tables = 1;
- }
- else {
- F_INDEX=1; F_END = 1; F_START = 1; batch_tables = 1;
- }
- } else {
- F_INDEX=1; F_END = 1; F_START = 1; batch_tables = 1;
- size_to_clean = (long int)filesize[2];
-
- while ((size_to_clean*batch_tables) < freeram) {
- batch_tables++;
- }
- if (batch_tables >1) batch_tables--;
- }
- //g_print("%d%d%d %d %u %d %d\n", F_INDEX, F_END, F_START, batch_tables, batch_tables*filesize[2], freeram, totalram);
-
- #else /* no READAHEAD*/
-
- if (freeram < size_to_clean) {
- if (filesize[0]>freeram) {
- F_INDEX=0; F_END = 0; F_START = 0; batch_tables = 1;
- }
- else if (filesize[1]>freeram) {
- F_INDEX=1; F_END = 0; F_START = 0; batch_tables = 1;
- }
- else {
- F_INDEX=1; F_END = 1; F_START = 0; batch_tables = 1;
- }
- } else {
- F_INDEX=1; F_END = 1; F_START = 1; batch_tables = 1;
- size_to_clean = (long int)filesize[2];
- while ((size_to_clean*batch_tables) < freeram) {
- batch_tables++;
- }
- if (batch_tables >1) batch_tables--;
- }
-
- // if ((batch_tables ==1) && (2*size_to_clean < totalram)) batch_tables++;
- #endif
-
- }
-
- #ifdef LIVECD
- int init_livecd(char *dir) {
-
- bzero(directory, strlen(directory));
- strncpy(directory, dir, strlen(dir));
- cols = 10000;
- offset = 10000;
- first_table=0;
- last_table=3;
- batch_tables = 4;
- table_type = 0;
-
- activate_launch_toggle();
-
- }
- #endif
-
-
- /* MAIN
- ==== */
-
- int main_cmd()
-
- {
- extern int optind;
- extern char *optarg;
- int h, i, k, t, table, f_t, l_t;
- int display_step;
-
- /* disabled for GUI
- while ((c=getopt(argc, argv, "qn:d:vt:o:si:f:l:"))>0) {
- switch ((char)c) {
- case 'd': strcpy(directory, optarg); break;
- case 't': cols = atoi(optarg); break;
- case 'o': offset = atoi(optarg); break;
- case 'i': ident_col = atoi(optarg); break;
- case 'v': verbose=1;break;
- case 's': stats = 1; init_stats(); break;
- case 'f': first_table = atoi(optarg); break;
- case 'l': last_table = atoi(optarg); break;
- case 'n': batch_tables = atoi(optarg); break;
- case 'q': quiet = 1; break;
- case '?': usage(argv[0]);break;
- }
- }
- */
-
- n_found=0;
-
- init_redux(offset,ident_col);
-
- /* find out how many ticks we have per second */
- #ifndef WIN32
- ticks = sysconf(_SC_CLK_TCK);
- #else /* WIN32 */
- ticks = CLOCKS_PER_SEC;
- #endif /* WIN32 */
-
- /* open all table files */
- if (!open_tables)
- if (!open_files(directory)) return -2;
-
- //read_file - GUI
- to_go = 3*hashes;
-
- if (!strcmp(crack_type, "LM"))
- crack_type_num=0;
- else
- crack_type_num=1;
-
- /* Eliminate empty ones: */
- for (i=0; i<hashes; i++) {
- if (!memcmp(lm_hash1[i],empty_hash,
- sizeof(lm_hash1[i]))) {
- strcpy(password1[i],"/EMPTY/");
- done1[i]=1;
- }
- if (!memcmp(lm_hash2[i],empty_hash,
- sizeof(lm_hash2[i]))) {
- done2[i]=1;
- }
- if (!memcmp(nt_hash[i], empty_nt_hash, sizeof(nt_hash[i])) || !strncmp((char *)nt_hash[i], "", 2)) {
- strcpy(password[i],"/EMPTY/");
- done_nt[i]=1;
- }
- if (done1[i])
- to_go--;
- if (done2[i])
- to_go--;
- if (done_nt[i])
- to_go--;
- if (done1[i] && done2[i] && done_nt[i])
- n_found++;
- if (!done1[i]) bzero(password1[i], sizeof(password1[i]));
- if (!done2[i]) bzero(password2[i], sizeof(password2[i]));
- if (!done_nt[i]) bzero(password[i], sizeof(password[i]));
-
- }
- fill_tree();
-
- if (!to_go)
- return(1);
-
- //g_print("togo: %d\n", to_go);
-
- /* search all passwords in all tables: */
- /* ================================== */
-
- display_step = cols/100;
- /* for each batch: */
- f_t = first_table; l_t= last_table;
-
- evaluate_ram();
-
- init_stats();
-
- /* g_print("cols %d, offset %d, f_t %d, l_t %d, chkpt1 %d, chkpt2 %d, batch %d, chars_size %d\n", cols, offset, f_t, l_t, chkpt1, chkpt2, batch_tables, chars_size);
- for (i=0; i<chars_size; i++)
- g_print("%c", charset[i]);
- g_print("\n");
- */
- for (t=f_t; t<= l_t; t+=batch_tables) {
-
- first_table = t;
- last_table = t+batch_tables-1>l_t? l_t : t+batch_tables-1;
- #if HAVE_READAHEAD
- if (t>f_t)
- clean_ram(size_to_clean);
- #elif defined(WIN32)
- for (i=first_table-batch_tables; i<first_table && (i>-1); i++) {
- if (F_START && startbuff[i]) {
- free(startbuff[i]);
- startbuff[i] = 0;
- }
- if (F_END && endbuff[i]){
- free(endbuff[i]);
- endbuff[i] = 0;
- }
- if (F_INDEX && indexbuff[i]){
- free(indexbuff[i]);
- indexbuff[i] = 0;
- }
- }
- #endif
-
- for (table=first_table; table<= last_table; table++)
-
- #if HAVE_READAHEAD
- /* readahead, preload the table in file cache
- * ED 28.8.2005 */
- {
- int readahead_result,fd;
- struct stat buf;
- size_t filesize;
-
- show_readahead_window(table);
- while (gtk_events_pending())
- gtk_main_iteration();
- if (F_START) {
- fd = fileno(startfile[table]);
- fstat(fd, &buf);
- filesize = (size_t)buf.st_size;
- readahead_result = readahead(fd,(loff_t)0,filesize);
- if(readahead_result == -1) perror("readahead");
- }
- if (F_END) {
- fd = fileno(endfile[table]);
- fstat(fd, &buf);
- filesize = (size_t)buf.st_size;
- readahead_result = readahead(fd,(loff_t)0,filesize);
- if(readahead_result == -1) perror("readahead");
- }
- if (F_INDEX) {
- fd = fileno(indexfile[table]);
- fstat(fd, &buf);
- filesize = (size_t)buf.st_size;
- readahead_result = readahead(fd,(loff_t)0,filesize);
- if(readahead_result == -1) perror("readahead");
- }
-
- hide_readahead_window();
- }
- /* end readahead */
- #elif defined(WIN32)
- {
- long size;
- DWORD dwRead;
-
- show_readahead_window(table);
- while (gtk_events_pending())
- gtk_main_iteration();
-
- if (F_START) {
- size = GetFileSize(startfile[table], NULL);
- if (startbuff[table] = (unsigned char*) malloc (size))
- ReadFile(startfile[table], startbuff[table], size, &dwRead, NULL);
- else
- F_START = 0;
- }
- if (F_END) {
- size = GetFileSize(endfile[table], NULL);
- if (endbuff[table] = (unsigned char*) malloc (size))
- ReadFile(endfile[table], endbuff[table], size, &dwRead, NULL);
- else
- F_END = 0;
- }
- if (F_INDEX) {
- size = GetFileSize(indexfile[table], NULL);
- if (indexbuff[table] = (unsigned char*) malloc (size))
- ReadFile(indexfile[table], indexbuff[table], size, &dwRead, NULL);
- else
- F_INDEX = 0;
- }
- hide_readahead_window();
- }
- #endif
-
-
- /* for each column of the tables */
- for (k=cols-1; k>=0; k--) {
-
- /* if (!quiet)
- if (!(k%display_step))
- display (-2,k);
- */
- update_statusbar(k);
-
- /* for each file containing a table: */
- for (table=first_table; table<=last_table; table++) {
- while (gtk_events_pending ()) {
- if (STOP) {
- close_files();
- return (0);
- }
- gtk_main_iteration ();
- }
-
- /* for each password: */
- for (h=0; h<hashes || !to_go; h++) {
- if (!crack_type_num) { //LM CRACK
- if (!done1[h]) {
- n_search++;
- if (find(lm_hash1[h], password1[h], k, table)) {
- change_tree(h);
- to_go--;
- done1[h]=1;
- if (done2[h]) {
- if (done_nt[h] || resolve_nt_hash(password1[h],password2[h],(char *)nt_hash[h],password[h]))
- {n_found++; to_go--; done_nt[h]=1;}
- change_tree(h);
- //display(h,k);
- update_statusbar(k);
- }
- if (!to_go) break;
- }
- }
-
- if (!done2[h]) {
- n_search++;
- if (find(lm_hash2[h], password2[h], k, table)) {
- change_tree(h);
- done2[h]=1;
- to_go--;
- if (done1[h]) {
- if (done_nt[h] || resolve_nt_hash(password1[h],password2[h],(char *)nt_hash[h],password[h]))
- {n_found++; to_go--; done_nt[h]=1;}
- change_tree(h);
- //display(h,k);
- update_statusbar(k);}
- if (!to_go) break;
- }
- }
- } else { //NT CRACK
- if (!done_nt[h]) {
- n_search++;
- if (find(nt_hash[h], password[h], k, table)) {
- change_tree(h);
- done_nt[h]=1;
- n_found++;
- to_go--;
- update_statusbar(k);
- if (!to_go) break;
- }
- }
- }
- }
- if (!to_go) break;
- }
- if (!to_go) break;
- }
- if (!to_go) break;
- }
-
- /* display hashes that have not been fully cracked: */
- for (h=0; h<hashes;h++)
- if (!done1[h] || !done2[h] || !done_nt[h]){
- if (!done1[h]) strcpy(password1[h],".......");
- if (!done2[h]) strcpy(password2[h],".......");
- if (!done_nt[h]) strcpy(password[h], "Not found");
- fill_tree();
- }
-
- print_stats();
- close_files();
- return (1);
- }
-